#ifndef POOL_H
#define POOL_H

#include "../Collection/List.h"

using namespace Lyt::Collection;

namespace Lyt
{
	template<typename _Type>
	class Pool
	{
		template<typename _Type>
		class Node
		{
		public:
			_Type Data;
			Node* Next;
		};

	private:
		int Total;
		int FreeCount;
		List<Node<_Type>*> Memory;
		Node<_Type>* FreeList;
		Node<_Type>* AllocatedList;

		void Grow(const int count)
		{
			FreeCount=count;
			Total=Total+count;
			Node<_Type>* data=new Node<_Type>[count];
			Init(data, count);
		}

		void Init(Node<_Type>* data, const int count)
		{
			Memory.Add(data);
			for (int i=0; i<count-1; i++)
				data[i].Next=&(data[i+1]);
			data[count-1].Next=FreeList;
			FreeList=data;
		}

		bool IsEnough()const
		{
			return FreeCount>0;
		}

	public:
		Pool(const int total=20)
		{
			FreeCount=0;
			Total=0;
			FreeList=0;
			AllocatedList=0;
			Grow(total);
		}

		~Pool()
		{
			Clear();
		}

		void Clear()
		{
			FreeCount=0;
			Total=0;
			FreeList=0;
			for (int i=0; i<Memory.GetCount(); i++)
				delete[] Memory[i];
			Memory.Clear();
		}

		_Type* Alloc()
		{
			if (!IsEnough()) Grow(Total*2);
			FreeCount--;
			Node<_Type>* node=FreeList;
			FreeList=FreeList->Next;
			node->Next=AllocatedList;
			AllocatedList=node;
			return &(node->Data);
		}

		void Free(_Type* object)
		{
			Node<_Type>* node=AllocatedList;
			AllocatedList=AllocatedList->Next;
			node->Data=*object;
			node->Next=FreeList;
			FreeList=node;
			FreeCount++;
		}
	};
};

#endif